<?php
/**
 * Hoffman Framework
 *
 * LICENSE
 *
 * This source file is subject to the GNU LGPL 2.1 license that is bundled
 * with this package in the file license.txt.
 * It is also available through the world-wide-web at this URL:
 * http://creativecommons.org/licenses/LGPL/2.1
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to annop@thaicyberpoint.com so we can send you a copy immediately.
 *
 * @package	   Hoffman
 * @author     Ford AntiTrust
 * @copyright  Copyright (c) 2008 Ford AntiTrust (http://www.thaicyberpoint.com/ford/blog)
 * @since	   Version Rv 0.2
 * @license    http://creativecommons.org/licenses/LGPL/2.1
 *             GNU LGPL 2.1
 * @filesource
 */

if (!defined('INDEX'))
    die('No direct script access allowed.');

/**
 * @see Zend_Registry
 */
require_once 'Zend/Registry.php';

/**
 * @see Zend_Session
 */
require_once 'Zend/Session.php';

/**
 * @see Zend_Locale
 */
require_once 'Zend/Locale.php';

/**
 * @see Hmf_Acl
 */
require_once 'Hmf/Acl.php';

/**
 * @see Hmf_Authen
 */
require_once 'Hmf/Authen.php';

/**
 * @see Hmf_Errors
 */
require_once 'Hmf/Errors.php';

/**
 * @see Hmf_View
 */
require_once 'Hmf/View.php';

/**
 * @see Hmf_Instance
 */
require_once 'Hmf/Instance.php';

/**
 * @see Hmf_Httppage
 */
require_once 'Hmf/Httppage.php';

/**
 * Controller
 *
 * @package		Hoffman
 * @subpackage	Hmf
 * @category	Controller
 * @author		Ford AntiTrust
 * @version     SVN: $Id: Controller.php 169 2010-02-18 10:38:15Z annop.s@gmail.com $
 * @link		http://www.thaicyberpoint.com/ford/blog/hmf
 */

abstract class Hmf_Controller extends Hmf {

    private $contentPage = array('index' => 'index');

    private $controllerName, $actionName;

    private $masterPage = "index";

    private $javascript = array();

    private $style = array();

    private $hasLoadFlowControllerConstructor = false;

    private $session = array();

    const NAMESPACE_SESSION_LOCALE = 'hmf.locale';

    abstract protected function onLoad();

    function __construct() {

        if (!$this->hasLoadFlowControllerConstructor) {

            $app_config = Zend_Registry::get('app_config');

            $this->hasLoadFlowControllerConstructor = true;

            $this->controllerName = preg_replace('/^controller_/', '', get_class($this));
            $this->actionName = Zend_Registry::get('action_name');

            if ($app_config['acl'] === true) {

                try {

                    Zend_Registry::set('app_acl', new Hmf_Acl());

                    foreach (Zend_Registry::get('acl') as $role => $data) {

                        if (array_key_exists('inherit', $data)) {
                            Zend_Registry::get('app_acl')->addRoleInherit($role, $data['inherit']);
                        } else {
                            Zend_Registry::get('app_acl')->addRole($role);
                        }
                        if (array_key_exists('allow', $data)) {
                            foreach ($data['allow'] as $aclControllerName => $aclActionList)
                                foreach ($aclActionList as $aclActionName)
                                    Zend_Registry::get('app_acl')->allowPermission($role, $aclControllerName, $aclActionName);
                        }
                        if (array_key_exists('deny', $data)) {
                            foreach ($data['deny'] as $aclControllerName => $aclActionList)
                                foreach ($aclActionList as $aclActionName)
                                    Zend_Registry::get('app_acl')->denyPermission($role, $aclControllerName, $aclActionName);
                        }
                    }

                    if ($app_config['authen.use'] === true) {

                        Zend_Registry::set('app_authen', Hmf_Authen::useStorage($app_config['authen.adapter']));

                        if (!Zend_Registry::get('app_acl')->isAllowed(Zend_Registry::get('app_authen')->getRole(), $this->getControllerName(), $this->getActionName()))
                            Hmf_Errors::accessDenied();

                    }

                } catch (Exception $e) {

                    Hmf_Errors::showError($e->getCode(), 'Acl class', $e->getMessage(), 'error');
                }
            }

            if($app_config['session.autoload'])
                $this->_startSession();

            if($app_config['language.use'])
                self::loadLocale();

            $this->onLoad();
        }
    }

    final function loadFlowControllerConstructor() {

        self::__construct();
    }

    public function __toString() {

        return $this->controllerName;
    }

    final private function loadLocale() {

        $this->_startSession();

        // load default settings
        self::loadTranslate();
        if ($this->_getLocaleFromSession() instanceof Zend_Locale) {
            $this->_setLocaleAndTranslate($this->_getLocaleFromSession());
            // load runtime settings
            self::loadTranslate();
        }

    }

    final private function loadTranslate($locale = 'default') {

        if (strcmp($locale, 'default') == 0) {
            $locale = self::_getLocale();
        }

        self::_translate()->change($locale);
        self::_translate()->change($locale, 'controller', array('controller' => self::getControllerName()));
        self::_translate()->change($locale, 'action', array('controller' => self::getControllerName(), 'action' => self::getActionName()));

    }

    final public function getControllerName() {

        return $this;
    }

    final public function getActionName() {

        return $this->actionName;
    }

    final public function useMasterPageCache($type = true, $lifetime = 300) {

        Hmf_View::useMasterPageCache($type, $lifetime);

        return $this;
    }

    final public function useContentPageCache($stickyKey = 'index', $type = true, $lifetime = 300) {

        Hmf_View::useContentPageCache($stickyKey, $type, $lifetime);

        return $this;
    }

    final public function useContentPage() {

        $numArgs = func_num_args();
        $args = func_get_args();

        if ($numArgs == 3)
            $this->contentPage[$args[0]] = array('controller' => $args[1], 'file' => $args[2]);
        elseif ($numArgs == 2)
            $this->contentPage[$args[0]] = array('controller' => $this->controllerName, 'file' => $args[1]);
        else
            $this->contentPage['index'] = array('controller' => $this->controllerName, 'file' => $args[0]);

        return $this;
    }

    final public function useMasterPage($name) {

        $this->masterPage = $name;

        return $this;
    }

    final public function createContentPage($stickyKey) {

        Zend_Registry::get('view')->createContentPage($stickyKey);
    }

    final public function getUseContentPage($stickKey = 'index') {

        return $this->contentPage[$stickKey]['controller'] . '/' . $this->contentPage[$stickKey]['file'];
    }

    final public function addJavaScript($fileName, array $options = array()) {

        Zend_Registry::get('view')->addJavaScript($fileName, $options);

        return $this;
    }

    final public function addStyleSheet($fileName, $media = 'all') {

        Zend_Registry::get('view')->addStyleSheet($fileName, $media);

        return $this;
    }

    final public function addHeadLink($attributes) {

        Zend_Registry::get('view')->addHeadLink($attributes);

        return $this;
    }

    final public function addFeed($url, $title = null, $type = 'application/rss+xml') {

        Zend_Registry::get('view')->addFeed($url, $title, $type);

        return $this;
    }

    final public function setTitle($val) {

        Zend_Registry::get('view')->setTitle($val);

        return $this;
    }

    final public function appendTitle($val) {

        Zend_Registry::get('view')->setTitle(Zend_Registry::get('view')->getTitle() . '' . $val);

        return $this;
    }

    final public function getUseMasterPage() {

        return $this->masterPage;
    }

    final public function _masterPage(array $val) {

        Zend_Registry::get('view')->appendMasterPageData($val);
        return $this;
    }

    final public function _contentPage($val, $stickyKey = 'index') {

        Zend_Registry::get('view')->appendContentPageData($stickyKey, $val);
        return $this;
    }

    final public function getInstanceModel($className) {

        return Hmf_Instance::getModel($className);
    }

    final public function getInstanceComponent($className, $args = array()) {

        $obj = Hmf_Instance::getComponent($className, $args);

        $obj->_locale()->setLocale($this->_getLocale());

        self::_translate()->change($this->_getLocale(), 'component', array('component' => $className));

        return $obj;
    }

    final public function _getPageNum() {

        $page = $this->_querystring('page');

        if (empty($page) or !is_numeric($page)) {
            return 1;
        } else {
            return $page;
        }
    }

    final public function _setLocale($locale) {

        self::_locale()->setLocale($locale);
        return $this;
    }

    final public function _getLocale() {

        return self::_locale()->getInstance();
    }

    final public function _setTranslate($locale) {

        self::_translate()->setLocale($locale);
        return $this;
    }

    final public function _getTranslate() {

        return self::_translate()->getInstance();
    }

    final public function _setLocaleAndTranslate($locale) {

        self::_setLocale($locale);
        self::_setTranslate($locale);
        return $this;
    }

    final public function _getLocaleFromSession() {

        if(Zend_Session::namespaceIsset(self::NAMESPACE_SESSION_LOCALE))
            return $this->_session(self::NAMESPACE_SESSION_LOCALE)->locale instanceof Zend_Locale ? $this->_session(self::NAMESPACE_SESSION_LOCALE)->locale : false;

        return false;
    }

    final public function _setLocaleToSession($locale) {

        if (is_string($locale))
            $locale = Hmf_Locale::createCoreInstanceLocale($locale);

        $this->_session('locale', (Hmf_Locale::isCoreInstanceLocale($locale) ? $locale : null), self::NAMESPACE_SESSION_LOCALE);
    }

    /**
     * Retrieve a member of the $_GET superglobal
     *
     * If no $key is passed, returns the entire $_GET array.
     *
     * @param string $key
     * @return mixed Returns null if key does not exist
     */
    final public function _querystring($key = null) {

        if (null === $key) {
            return $_GET;
        }

        return (isset($_GET[$key])) ? $_GET[$key] : null;
    }

    /**
     * Retrieve a member of the $_POST superglobal
     *
     * If no $key is passed, returns the entire $_POST array.
     *
     * @param string $key
     * @return mixed Returns null if key does not exist
     */
    final public function _post($key = null) {

        if (null === $key) {
            return $_POST;
        }

        return (isset($_POST[$key])) ? $_POST[$key] : null;
    }

    /**
     * Retrieve a member of the $_POST superglobal
     *
     * If no $key is passed, returns the entire $_POST array.
     *
     * @param string $key
     * @return mixed Returns null if key does not exist
     */
    final public function _cookie($key = null) {

        if (null === $key) {
            return $_COOKIE;
        }

        return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : null;
    }

    /**
     * Retrieve a member of the $_SERVER superglobal
     *
     * If no $key is passed, returns the entire $_SERVER array.
     *
     * @param string $key
     * @return mixed Returns null if key does not exist
     */
    final public function _server($key = null) {

        if (null === $key) {
            return $_SERVER;
        }

        return (isset($_SERVER[$key])) ? $_SERVER[$key] : null;
    }

    /**
     * Retrieve a member of the $_SERVER superglobal
     *
     * If no $key is passed, returns the entire $_SERVER array.
     *
     * @param string $key
     * @return mixed Returns null if key does not exist
     */
    final public function _env($key = null) {

        if (null === $key) {
            return $_ENV;
        }

        return (isset($_ENV[$key])) ? $_ENV[$key] : null;
    }

    final protected function _startSession(){
        try {

            if(!Zend_Session::isStarted()) {
                /**
                 * Start Session
                 */
                Zend_Session::start();

                $app_config = Zend_Registry::get('app_config');

                $this->session[$app_config['session.default.namespace']] = new Zend_Session_Namespace($app_config['session.default.namespace']);
            }
        } catch (Exception $e) {
            /**
             * Default Error Exception
             */
            Hmf_Errors::showError($e->getCode(), 'Session Startup', $e->getMessage(), 'error');
        }
    }

    final public function _getSession($namespace = null) {

        $this->_startSession();

        $app_config = Zend_Registry::get('app_config');

        $namespace = is_null($namespace) ? $app_config['session.default.namespace'] : $namespace;

        if (!array_key_exists($namespace, $this->session)) {
            $this->session[$namespace] = new Zend_Session_Namespace($namespace);
        }
        return $this->session[$namespace];
    }

    final public function _setSession($key, $data, $namespace = null) {

        $this->_startSession();

        $app_config = Zend_Registry::get('app_config');

        $namespace = is_null($namespace) ? $app_config['session.default.namespace'] : $namespace;

        if (!array_key_exists($namespace, $this->session)) {
            $this->session[$namespace] = new Zend_Session_Namespace($namespace);
        }

        $this->session[$namespace]->$key = $data;
    }

    final public function _go() {

        $args = func_get_args();
        return call_user_func_array(array('Hmf_Httppage', 'redirect'), $args);
    }

    final public function __call($method, $args) {

        if (strcmp($method, '_session') == 0) {
            $numArgs = count($args);
            switch ($numArgs) {
                case 0:
                    return self::_getSession();
                    break;
                case 1:
                    return self::_getSession($args[0]);
                    break;
                case 2:
                    self::_setSession($args[0], $args[1]);
                    break;
                case 3:
                    self::_setSession($args[0], $args[1], $args[2]);
                    break;
            }
        }
        return parent::__call($method, $args);
    }

}
?>